home *** CD-ROM | disk | FTP | other *** search
- ;-------------------------fpin begins--------------------------+
- ; from BLUEBOOK OF ASSEMBLY ROUTINES FOR IBM PC & XT.
- ; page : 88
- ;
- ; NAME FPIN
- ;
- ; ROUTINE FOR CONVERSION FROM EXTERNAL TO INTERNAL FLOATING POINT
- ;
- ; FUNCTION: This routine accepts an ASCII decimal floating point number
- ; from a std input device and converts it to internal binary floating
- ; point.
- ;
- ; INPUT: The characters of the floating point number are received in ASCII
- ; through a call to a std input routine. The decimal floating point number
- ; has an optional sign, followed by decimal digits of the mantissa with one
- ; embedded decimal point. Following the mantissa is an optional exponent
- ; which starts with the letter 'E', then an optional sign, then a decimal
- ; number. It is possible to get erroneous results if the number is too
- ; large or small to be stored as a single precision binary floating point
- ; number.
- ;
- ; OUTPUT: Upon exit a single precision binary floating point number is in
- ; SFPBUFF. The single precision floating point number has a 24-bit binary
- ; mantissa, a sign bit, and an 8-bit exponent biased by 128.
- ;
- ; REGISTERS USED: No registers are modified.
- ;
- ; SEGMENTS REFERENCED: The data segment contains the variables FPTEMP1,
- ; FPTEMP2, and SFPBUFF.
- ;
- ; ROUTINES CALLED: STDIN, FPINDIGT, FPTMUL, FPTDIV and FPTNORM
- ;
- ; SPECIAL NOTES: Equates are used to shorten address fields.
- ;
- ; ROUTINE TO CONVERT FROM ASCII EXTERNAL TO INTERNAL FLOATING POINT
- ;
- fpin proc far
- ;
- push di ; save registers
- push si
- push dx
- push cx
- push ax
- ;
- ; clear fp temp1 buffer
- lea di,fptemp1 ; point to fptemp1
- mov al,0 ; digit = 0
- call fpindigt ; store digit
- ;
- ; clear the decimal flap and the count
- mov decflag,0 ; clear the flag
- mov decexp,0 ; clear the decimal exponent
- ;
- ; look for the sign
- call stdin ; look for sign
- cmp al,'-' ; minus ?
- jz fpin1 ; store it
- cmp al,'+' ; plus ?
- jz fpin2 ; ignore it
- jmp fpin3 ; anything else is a player
- ;
- fpin1:
- ; set sign as a negative
- mov fptemp1b10,80h ; put sign in place
- ;
- fpin2:
- call stdin ; get next digit
- ;
- fpin3:
- cmp al,'.' ; check for decimal point
- jne fpin4 ; press on if not
- ;
- ; set decimal flag
- cmp decflag,0 ; decimal flag already set ?
- jne fpin5 ; exit if not the first
- mov decflag,0FFh ; set it now.
- jmp fpin2 ; go back for a digit
- ;
- fpin4:
- sub al,30h ; bring down from ASCII
- jl fpin5 ; too low ?
- cmp al,9
- jg fpin5 ; too high ?
- jmp fpin6 ; got a digit
- ;
- fpin5:
- jmp fpin15 ; end of mantissa
- ;
- ; load digit as a floating point number
- fpin6:
- lea di,fptemp2 ; point to fptemp2
- call fpindigt ; put in the digit
- ;
- ; multiply result by 10
- lea di,fptemp1 ; point to fptemp1
- call fptmul ; multiply by 10
- ;
- ; pick one with a larger exponent
- mov cx,fptemp1w11 ; get sign of fptemp1
- sub cx,fptemp2w11 ; subtract sign of fptemp2
- je fpin11 ; skip if equal
- jg fpin9 ; if exponent fptemp2 is less
- ;
- fpin7:
- ; shift the bits
- sar fptemp1w8,1 ; shift all bits right
- rcr fptemp1w6,1 ; carry on
- rcr fptemp1w4,1
- rcr fptemp1w2,1
- rcr fptemp1w0,1
- loop fpin8
- ;
- ; set the exponent
- mov ax,fptemp2w11 ; get exponent of fptemp2
- mov fptemp1w11,ax ; put in exponent of fptemp1
- ;
- jmp fpin11 ; done withthis case
- ;
- fpin9:
- ;
- ; exponent of fptemp2 is less than exp of fptemp1
- ;
- fpin10:
- ; shift the bits
- sar fptemp2w8,1 ; shift all bits right
- rcr fptemp2w6,1 ; carry on
- rcr fptemp2w4,1
- rcr fptemp2w2,1
- rcr fptemp2w0,1
- loop fpin10
- ;
- ; set the exponent
- mov ax,fptemp1w11 ; get exp of fptemp1
- mov fptemp2w11,ax ; put in exp of fptemp2
- jmp fpin11 ; end of this case
- ;
- fpin11:
- ;
- ; add the digit to result
- ;
- mov cx,5 ; for a count of 5 words
- lea di,fptemp1 ; di points to fptemp1
- lea si,fptemp2 ; si points to fptemp2
- clc
- ;
- fpin12:
- mov ax,[si] ; get 16-bit digit from fptemp1
- inc si ; point to next 16-bit digit
- inc si
- adc [di],ax ; add to 16-bit digit of fptemp2
- inc di ; point to next 16-bit digit
- inc di
- loop fpin12
- ;
- ; normalize
- lea di,fptemp1 ; point to fptemp1
- call fptnorm ; renormalize it
- ;
- fpin13:
- ;
- ; decrement decimal exponent if dec flag is on
- cmp deflag,0 ; check decimal flag
- je fpin14 ; skip if not set
- dec decexp ; dec exponent if set
- ;
- fpin14:
- ; adjust for the decimal point
- add al,30h ; restore ASCII
- and al,5Fh ; upper or lower case
- cmp al,'E' ; is it E for Exponent ?
- jne fpin16
- ;
- ; grab exponent
- ;
- call sgnd16in ; get signed decimal exponent
- add dexexp,dx ; add it to our current value
- ;
- fpin16:
- ; check for sign of decimal exponent
- mov cx,decexp ; get decimal exponent
- cmp cx,0 ; check its sign
- jg fpin17 ; if positive
- jl fpin18 ; if negative
- ;
- ; zero count
- jmp fpin20 ; done if exponent is zero
- ;
- ; positive decimal exponent
- fpin17:
- push cx ; save count = decimal exponent
- ;
- ; multiply result by 10
- lea di,fptemp1 ; point to fptemp1
- call fptmul ; multiply by 10
- ;
- ; normalize
- lea di,fptemp1 ; point to fptemp1
- call fptnorm ; renormalize it
- ;
- pop cx ; restore the count
- loop fpin17
- ;
- jmp fpin20 ; end of this case
- ;
- fpin18:
- ; negative count
- neg cx ; absolute value of exponent
- fpin19:
- push cx ; save count
- ;
- ; divide mantissa by 10
- lea di,fptemp1 ; point to fptemp1
- call fptdiv ; divide by 10
- ;
- ; normalize
- lea di,fptemp1 ; point to fptemp1
- call fptnorm ; renormalize it
- ;
- pop cx ; restore count
- loop fpin19
- ;
- fpin20:
- call tfp2sfp ; convert to single precision
- ;
- pop ax ; restore registers
- pop cx
- pop dx
- pop si
- pop di
-
- ;
- ret ; return
- ;
- fpin endp
- ;-------------------------fpin ends---------------------------+